﻿///
/// Authors: Lee Gary 
///
/// Date: 24/09/2010
///
/// Purpose: 
///
/// UNC connection helper using unmanaged dlls to connect to Windows Workstation via UNC
/// 
/// 
/// Future:
/// 1.) Find a unmanaged code expert and discuss the impacts of not disconnecting the user
/// 
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace GSPMigratorCore.UNC
{    
    public static class GSPUNCHelper
    {
        #region unmanaged win32

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, 
            int dwLogonType, int dwLogonProvider, out IntPtr phToken);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private extern static bool CloseHandle(IntPtr handle);

        #endregion

        #region enums for extern dlls
        
        /// <summary>
        ///  Specifies the logon type
        /// </summary>
        
        private enum LogonType
        {
            /// 
            /// This logon type is intended for users who will be interactively using the computer
            /// 
            Interactive = 2,
            /// 
            /// This logon type is intended for high performance servers to authenticate plaintext passwords. 
            /// 
            Network = 3,
            /// 
            /// This logon type is intended for batch servers, where processes may be executing on behalf of a user without their direct intervention.
            /// 
            Batch = 4,
            /// 
            /// Indicates a service-type logon. The account provided must have the service privilege enabled.
            /// 
            Service = 5,
            /// 
            /// This logon type is for GINA DLLs that log on users who will be interactively using the computer.
            /// 
            Unlock = 7
        }
        
        /// <summary>
        /// Specifies the logon provider
        /// </summary>
        
        private enum LogonProvider
        {
            /// 
            /// Use the standard logon provider for the system.
            /// 
            Default = 0,
            /// 
            /// Use the negotiate logon provider. (WINNT50)
            /// 
            Negotiate = 3,
            /// 
            /// Use the NTLM logon provider (WINNT40)
            /// 
            NTLM = 2,
            /// 
            /// Use the Windows NT 3.5 logon provider.
            /// 
            WinNT35 = 1
        }

        #endregion

        public static bool ConnectUser(string username, string domain, string password, out IntPtr token)
        {
            bool success = false;
            WindowsIdentity wi;
            token = new IntPtr();
            if (LogonUser(username, domain, password, (int)LogonType.Interactive, (int)LogonProvider.Default, out token))
            {
                wi = new WindowsIdentity(token);
                success = true;
            }
            else
            {
                success = false;
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            return success;
        }

        public static bool DisconnectUser(IntPtr token)
        {
            bool success = false;
            try
            {
                if (!CloseHandle(token))//if cant close
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            catch (Exception ex)
            { 
                //log
            }
            return success;
        }
    }
}